using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using OpenWaves.Pagination;

namespace OpenWaves.Web.Pagination
{
    public class PageViewModel
    {
        private readonly int index;
        public int Number
        {
            get
            {
                Contract.Ensures(Contract.Result<int>() >= 1);
                return this.index + 1;
            }
        }

        private readonly bool isFirst;
        private readonly bool isLast;
        private readonly bool isCurrent;
        private readonly int firstItemIndex;
        private readonly int lastItemIndex;
        
        public int FirstItemNumber
        {
            get
            {
                Contract.Ensures(Contract.Result<int>() >= 1);
                return this.firstItemIndex + 1;
            }
        }

        public int LastItemNumber
        {
            get
            {
                Contract.Ensures(Contract.Result<int>() >= 1);
                return this.lastItemIndex + 1;
            }
        }

        public bool IsFirst
        {
            get { return isFirst; }
        }

        public bool IsLast
        {
            get { return isLast; }
        }

        public bool IsCurrent
        {
            get { return isCurrent; }
        }

        public int FirstItemIndex
        {
            get { return firstItemIndex; }
        }

        public int LastItemIndex
        {
            get { return lastItemIndex; }
        }

        public int Index
        {
            get { return index; }
        }

        public PageViewModel(int index, bool isFirst, bool isLast, bool isCurrent, int firstItemIndex, int lastItemIndex)
        {
            Contract.Requires<ArgumentOutOfRangeException>(index >= 0);
            Contract.Requires<ArgumentOutOfRangeException>(firstItemIndex >=0);
            Contract.Requires<ArgumentOutOfRangeException>(lastItemIndex >= firstItemIndex);

            this.index = index;
            this.isFirst = isFirst;
            this.isLast = isLast;
            this.isCurrent = isCurrent;
            this.firstItemIndex = firstItemIndex;
            this.lastItemIndex = lastItemIndex;
        }
    }

    public class PageViewModel<T> : PageViewModel
    {
        private IEnumerable<T> items; 
        public IEnumerable<T> Items
        {
            get
            {
                Contract.Ensures(Contract.Result<IEnumerable<T>>() != null);

                if (this.items == null)
                    this.items = this.page.GetItemsRange().ToList();
                return this.items;
            }
        }

        private readonly IPage<T> page;

        public PageViewModel(IPage<T> page, bool isFirst, bool isLast, bool isCurrent)
            :base(page.Index, isFirst, isLast, isCurrent, page.FirstItemIndex, page.LastItemIndex)
        {
            Contract.Requires<ArgumentNullException>(page != null);

            this.page = page;
        }
    }
}